package es.duma.util.xsl;

import es.duma.util.config.Configurator;
import es.duma.util.log.Log;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import java.util.ArrayList;
import java.util.List;

/**
 * Extiende la clase Thread para poder lanzar peticiones REST de manera concurrente desde 
 * otra clase.
 */
public class ConcurrentConexion extends Thread{
    
    /**
     * Direccion url donde realizar la peticion rest
     */
    private String urlREST;
    
    /**
     * Posicion dentro del conjunto total de peticiones
     */
    private int position;
    
    /**
     * Lista sincronizada donde se almacenan los resultados parciales de cada hilo (recurso compartido)
     */
    private ListaResultados results; 
    
    /**
     * Numero de hilos que han concluido sus peticiones
     */
    int hilosTerminados[]; 
    
    /**
     * Nombre o identificador para mostrar en los mensajes de log producidos por esta clase
     */
    private static final String LOG_ID="[Concurrent Conexion]";
    
    /**
     * 
     */
     private static final int DEFAULT_TIME_OUT=3000;
    
    
    /**
     * Constructor del hilo de conexiones concurrentes REST
     * 
     * @param url
     * @param position
     * @param results
     * @param hilosTerminados
     */
    public ConcurrentConexion(String url, int position, ListaResultados results, int hilosTerminados[]){
        Log.debug(this," Creado hilo"+position+" Peticion REST "+url);
        this.urlREST=url;
        this.position=position;
        this.results=results;  
        this.hilosTerminados=hilosTerminados;
        
    }
    
    /**
     * Metodo run del hilo (esta clase extiende Thread)
     */
    public void run() {
        // Presenta en pantalla informacion sobre este hilo en particular
        Log.debug(this,""+Thread.currentThread());
        Log.debug(this,"[Hilo "+position+"]Inicio run. Hilo "+position);
        
        // Se realiza la peticion REST y se guarda el resultado en el array
        InputStream in=null;
        HttpURLConnection connection=null;
        URL url;
        Long ini=System.currentTimeMillis();
        
        String resultado="";
        
        
        try {
            url = new URL(urlREST);
            connection = (HttpURLConnection)url.openConnection();
            Log.debug(this,"[Hilo "+position+"] Conexion Http establecida.");
            
            //Establecemos el time-out de las conexiones obteniendolo del fichero de propiedades
            int time_out=DEFAULT_TIME_OUT; 
            try{
                time_out=Integer.parseInt(Configurator.getPropertieValue("TIME_OUT_HTTP"));
            }catch (NumberFormatException e){
                Log.error(this,"El valor obtenido del .properties para fijar el time_out htttp no es valido. Se fija el valor por defecto");
                time_out=DEFAULT_TIME_OUT;
            }
                
            Log.debug(this,"Se fija el time_out para la conexion http a "+time_out+" ms");
            connection.setReadTimeout(time_out);
            // Se obtiene el inputStream
            in = connection.getInputStream();
            
            // El inputStream se pasa a un String
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            StringBuilder result = new StringBuilder();
            String line = null;
            try {
                while ((line = br.readLine()) != null) {
                    result.append(line + "\n");
                }
                br.close();
                resultado=result.toString();
             } catch (IOException e) {
                Log.error(this,"[Hilo "+position+"] Error al obtener el inputStream en un String. "+e);
                resultado="<Error>Error al obtener el inputStream en un String</Error>";
             }
            
        }catch (MalformedURLException e) {
            Log.error(this,"[Hilo "+position+"] Error al formar la URL. "+e);
        }catch (IOException e) {
            Log.error(this,"[Hilo "+position+"] Error al obtener el inputStream en la conexion. "+e);
            resultado="<Error>TIME_OUT</Error>";
        }finally{
            Log.debug(this,"[Hilo "+position+"] Se realiza la desconexion http");
            connection.disconnect(); 
            Long fin=System.currentTimeMillis();
            Log.debug(this,"[Hilo "+position+"] [TIME] Tiempo empleado en la conexion HTTP: "+urlREST+" "+(fin-ini)+ "ms");
            
            //Mostramos en resultado de la peticion REST por log
            //Log.debug(this,result.toString());
            
            // La conexion ha terminado, Se incrementa el contador de conexiones terminadas
            Log.debug(this,"[Hilo "+position+"] El resultado de la peticion http se intenta almacenar en la lista compartida en la posicion "+position+"\n");
            results.addDatoSync(resultado,position);
            Log.debug(this,"[Hilo "+position+"] Fin run.");

        }

    }
    
}
